package org.chen.jenkins.client.service;

import com.alibaba.fastjson.JSONObject;
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.chen.jenkins.client.dto.BuildDTO;
import org.chen.jenkins.client.entity.JenkinsJobInfo;
import org.chen.jenkins.client.entity.TfsProject;
import org.chen.jenkins.client.entity.TfsResult;
import org.chen.jenkins.client.utils.OkHttp3Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author chensj
 * @date 2019-09-18 20:20
 */
@Service
@Slf4j
public class JenkinsService {

    /**
     * logger
     */
    private static final Logger logger = LoggerFactory.getLogger(JenkinsService.class);

    private final static String SPLIT_FLAG = "__";
    private final static String JENKINS_PREFIX = "DEVOPS";

    private final static String JENKINS_URL = "http://172.16.9.242:8080";
    private final static String JENKINS_USERNAME = "chensj";
    private final static String JENKINS_PASSWORD = "123";

    private final static String JENKINS_TEST_URL = "http://172.16.9.242:9080";
    private final static String JENKINS_TEST_USERNAME = "admin";
    private final static String JENKINS_TEST_PASSWORD = "admin";

    private synchronized JenkinsServer getServerInstance() throws URISyntaxException {
        return new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD);
    }

    private synchronized JenkinsServer getServerTestInstance() throws URISyntaxException {
        return new JenkinsServer(new URI(JENKINS_TEST_URL), JENKINS_TEST_USERNAME, JENKINS_TEST_PASSWORD);
    }

    /**
     * 获取jenkins job信息
     */
    public Map<String, Job> getJobs() throws URISyntaxException, IOException, InterruptedException {
        return getServerInstance().getJobs();
    }

    /**
     * 创建job
     */
    public void createJob() throws URISyntaxException, IOException {
        getServerInstance().createJob(
                "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                "<?xml version='1.1' encoding='UTF-8'?>\n<maven2-moduleset plugin=\"maven-plugin@3.4\"> " +
                        "</maven2-moduleset>");
    }

    /**
     * 任务删除
     */
    public void deleteJob() throws URISyntaxException, IOException {
        getServerInstance().deleteJob(
                "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    }

    /**
     * 获取指定job详情信息
     *
     * @param jobName 名称
     */
    public String getDetailList(String jobName) throws URISyntaxException, IOException, InterruptedException {
        Map<String, Job> jobs = getServerInstance().getJobs();
        Job job = jobs.get(jobName);
        JobWithDetails details = job.details();
        logger.info("JobWithDetails: [{}]", ReflectionToStringBuilder.toString(details));
        logger.info("builds first element: [{}]", ReflectionToStringBuilder.toString(details.getBuilds().get(0)));
        logger.info("build first build: [{}]", ReflectionToStringBuilder.toString(details.getFirstBuild()));
        logger.info("build last  build: [{}]", ReflectionToStringBuilder.toString(details.getLastBuild()));
        logger.info(ReflectionToStringBuilder.toString(details, ToStringStyle.MULTI_LINE_STYLE));
        return ReflectionToStringBuilder.toString(details, ToStringStyle.MULTI_LINE_STYLE);
    }

    /**
     * 获取指定job构建xml
     *
     * @param jobName 名称
     */
    public String getJobXml(String jobName) throws URISyntaxException, IOException, InterruptedException {
        String jobXml = getServerInstance().getJobXml(jobName);
        return jobXml;
    }


    /**
     * 通过制定的任务复制任务
     *
     * @param jobName 名称
     */
    public String createJobByJobXml(String jobName) throws URISyntaxException, IOException, InterruptedException {
        String jobXml = getServerInstance().getJobXml(jobName);
        log.info("jobName:{} jobXML:{}", jobName, jobXml);
        getServerTestInstance().createJob(jobName, jobXml);
        return jobXml;
    }

    /**
     * 执行指定job
     *
     * @param jobName 名称
     */
    public QueueReference build(String jobName) throws URISyntaxException, IOException, InterruptedException {
        Map<String, Job> jobs = getServerInstance().getJobs();
        Job job = jobs.get(jobName);
        return job.build();
    }

    /**
     * 查询构建job下指定构建NUM下的构建信息的
     *
     * @param jobName  名称
     * @param buildNum 构件号
     */
    public String buildItemInfo(String jobName, int buildNum) throws URISyntaxException, IOException,
            InterruptedException {
        Map<String, Job> jobs = getServerInstance().getJobs();
        Job job = jobs.get(jobName);
        Build buildByNumber = job.details().getBuildByNumber(buildNum);
        return ReflectionToStringBuilder.toString(buildByNumber, ToStringStyle.MULTI_LINE_STYLE);
    }

    /**
     * 获取查询job下是否处于构建状态
     *
     * @param jobName 名称
     */
    public BuildDTO checkIsBuild(String jobName) throws URISyntaxException, IOException {
        Map<String, Job> jobs = getServerInstance().getJobs();
        Job job = jobs.get(jobName);
        JobWithDetails details = job.details();
        Build lastBuild = details.getLastBuild();
        Build lastCompletedBuild = details.getLastCompletedBuild();
        BuildWithDetails details1 = lastBuild.details();
        BuildDTO dto = new BuildDTO();
        dto.setJobName(jobName);
        dto.setIsRunning(details1.isBuilding());
        dto.setCurrentBuildNumber(lastBuild.getNumber() + "");
        dto.setBuildResult(details1.getResult() == null ? "构建中" : details1.getResult().toString());
        dto.setBuildName(details1.getDisplayName());
        if (lastBuild.getNumber() == lastCompletedBuild.getNumber()) {
            dto.setBuildLog(details1.getConsoleOutputText());
            dto.setStatus("构建完成");
            String format = String.format("%s 构建完成, 最后一次构建是[%s], \n当前状态[%s], 构建结果[%s], \n构建日志:\n[%s]", jobName,
                    lastBuild.getNumber(),
                    details1.isBuilding(), details1.getResult(), details1.getConsoleOutputText());
            logger.info(format);
            return dto;
        } else {
            dto.setBuildLog(details1.getConsoleOutputText());
            dto.setStatus("构建中...");
            String format = String.format("%s 构建中..., 最后一次构建是[%s], \n当前状态[%s], 构建结果[%s], \n构建日志:\n[%s]", jobName,
                    lastBuild.getNumber(),
                    details1.isBuilding(), details1.getResult(), details1.getConsoleOutputText());
            logger.info(format);
            return dto;
        }

    }


    /**
     * 通过制定的任务复制任务
     *
     * @param jobName 名称
     * @return
     */
    public List<JenkinsJobInfo> createJobForAll(String jobName) throws URISyntaxException, IOException,
            InterruptedException {
        String jobXml = getServerInstance().getJobXml(jobName);
        List<TfsProject> results = getResult();
        String[] jobNames = jobName.split(SPLIT_FLAG);
        List<JenkinsJobInfo> allJobNames = results.stream().map(item -> {
            String moduleName = jobNames[2];
            String newJobName = JENKINS_PREFIX + SPLIT_FLAG +
                    jobNames[0] + SPLIT_FLAG + jobNames[1] + SPLIT_FLAG + item.getName() + SPLIT_FLAG + item.getId();
            String replace = jobXml.replace(jobName, newJobName);
            String newJobXML = replace.replace(moduleName, item.getName());
            if (jobNames[0].equals("CD")) {
                newJobXML = newJobXML.replace("CI", "DEVOPS_CI");
            }
            JenkinsJobInfo info = new JenkinsJobInfo();
            info.setJobName(newJobName);
            info.setJobXml(newJobXML);
            return info;
        }).collect(Collectors.toList());
        for (JenkinsJobInfo jobInfo : allJobNames) {
            JobWithDetails job = getServerTestInstance().getJob(jobInfo.getJobName());
            if (job == null) {
                log.info("create job {}", jobInfo.getJobName());
                getServerInstance().createJob(jobInfo.getJobName(), jobInfo.getJobXml());
            } else {
                log.info("update job {}", jobInfo.getJobName());
                getServerInstance().updateJob(jobInfo.getJobName(), jobInfo.getJobXml());
            }

        }

        return allJobNames;
    }

    /**
     * 删除全部任务
     *
     * @return
     */
    //public String deleteJobForAll() throws URISyntaxException, IOException,
    //        InterruptedException {
    //    Map<String, Job> jobs = getServerTestInstance().getJobs();
    //    int count = 0;
    //    Set<String> keySets = jobs.keySet();
    //    for (String keySet : keySets) {
    //        getServerTestInstance().deleteJob(keySet);
    //        log.info("delete job {}", keySet);
    //        count++;
    //    }
    //    return String.format("jenkins :[%s] 合计删除任务 [%s]", JENKINS_TEST_URL, count);
    //}

    /**
     * TFS接口获取结果信息
     *
     * @return
     */
    private List<TfsProject> getResult() {
        Map<String, String> headerMap = new HashMap<>(8);
        headerMap.put("Content-Type", "application/x-www-form-urlencoded");
        headerMap.put("Authorization", "Basic Omw1N3BleWZxYW9jM3prYXUzeHVobm9qN3BpczZ6d3dncTczNnlwbzdscjRxNDRybjNkY2E" +
                "=");
        headerMap.put("User-Agent", "OkHttp Example");
        String result = OkHttp3Util.sendByGetWithHeader("http://tfs2018-web.winning.com.cn:8080/tfs/WINNING-6.0/W" +
                ".in-MVP/_apis/git/repositories?api-version=4.1", headerMap);
        TfsResult tfsResult = JSONObject.parseObject(result, TfsResult.class);
        return tfsResult.getValue().stream().filter(item -> {
            if (item.getName().contains("allinone") || item.getName().contains("winning-webui")
                    || item.getName().contains("winning-web") || item.getName().contains("devops")) {
                return false;
            }
            return true;
        }).collect(Collectors.toList());
    }

    /**
     * 根据结果删除
     *
     * @return
     * @throws URISyntaxException
     * @throws IOException
     */
    public String deleteAllJobByResult() throws URISyntaxException, IOException {
        String[] args = {"CI", "60"};
        String[] args2 = {"CD", "60"};
        int count = 0;
        List<TfsProject> results = getResult();
        List<String> allJobNames = results.stream().map(item -> {
            return JENKINS_PREFIX + SPLIT_FLAG +
                    args[0] + SPLIT_FLAG + args[1] + SPLIT_FLAG + item.getName() + SPLIT_FLAG + item.getId();
        }).collect(Collectors.toList());
        for (String name : allJobNames) {
            getServerInstance().deleteJob(name);
            log.info("delete job {}", name);
            count++;
        }
        allJobNames = results.stream().map(item -> {
            return JENKINS_PREFIX + SPLIT_FLAG +
                    args2[0] + SPLIT_FLAG + args[1] + SPLIT_FLAG + item.getName() + SPLIT_FLAG + item.getId();
        }).collect(Collectors.toList());
        for (String name : allJobNames) {
            getServerInstance().deleteJob(name);
            log.info("delete job {}", name);
            count++;
        }
        return String.format("jenkins :[%s] 合计删除任务 [%s]", JENKINS_TEST_URL, count);
    }
}
